package com.example.wechat114.commons;

import com.example.wechat114.entity.WxUser;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Point;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
 * @author CHENCHEN
 * @create 2021-03-29 14:55
 */
@Component
public class Constant {

    /** Logger实例 */
    static final Logger logger = LoggerFactory.getLogger(Constant.class);

    //测试号域名
    public static final String URL = "http://guowang.nat300.top";
    //测试账号token
    public static final String TOKEN = "E";
    //测试账号APPID
    public static final String APPID = "wx7e6746fc8fad1f65";
    //测试账号APPSECRET
    public static final String APPSECRET = "5c73cd33f3df1524f90b78742c4e2191";
    //静默授权
    public static final String SNSAPI_BASE = "snsapi_base";
    //用户手动同意授权
    public static final String SNSAPI_USERINFO = "snsapi_userinfo";
    //挂号成功模板
    public static final String TEMPLATE_ID_REGISTER_SUCCESS = "6g2uNnoGlPF64NS5IAIZrfbEG-Zp-LlDW8veb86UjtY";
    //退号成功模板
    public static final String TEMPLATE_ID_WITHDRAWAL_SUCCESS = "CcHaJDSWGyBJZsxJ1m0vT2hF-cMcbnSKJ0cN21qiYto";


    private static RedisTemplate redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        Constant.redisTemplate = redisTemplate;
    }

    /**
     * 通过redisGEO计算两地经纬度距离
     * @param blongitude B1经度
     * @param blatitude  B1维度
     * @param ulongitude B2经度
     * @param ulatitude  B2维度
     * @return
     */
    public static double getDistance(double blongitude, double blatitude, double ulongitude, double ulatitude){
        GeoOperations geoOperations = redisTemplate.opsForGeo();
        //首先存入客户端上传的经纬度和指定地点的经纬度
        Map<String,Object> map = new HashMap<>();
        map.put("ZB",new Point(blongitude, blatitude));
        map.put("GZ",new Point(ulongitude, ulatitude));
        // 将这些地址数据保存到redis中
        geoOperations.geoAdd("GET_DISTANCE",map);
        // 调用方法,计算之间的距离;
        double value = geoOperations.geoDist("GET_DISTANCE", "ZB", "GZ", RedisGeoCommands.DistanceUnit.KILOMETERS).getValue();
        BigDecimal bg = new BigDecimal(value);
        double f1 = bg.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }

    /**
     * 微信网页授权
     * @param uri
     * @return
     */
    public static String oAuth(String uri, String scope){
        try {
            uri = URLEncoder.encode(uri, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return WechatAPI.OAUTH_URL.replace("APPID", APPID).replace("REDIRECT_URI", uri).replace("SCOPE", scope);
    }

    /**
     * 获取AccessToken接口
     * @return
     */
    public static String getAccessToken() {
        Object access_token = redisTemplate.opsForValue().get("access_token");
        if(access_token == null){
            String url = WechatAPI.ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
            String s = HttpClientUtil.doGet(url);
            logger.debug("全局access_token ： " + s);
            JSONObject jsonObject = new JSONObject(s);
            if(jsonObject.has("access_token")){
                access_token = jsonObject.get("access_token");
                redisTemplate.opsForValue().set("access_token", access_token.toString(), 2, TimeUnit.HOURS);
            }
        }
        return access_token.toString();
    }




    /**
     * 临时使用获取AccessToken
     * @return
     */
    public static String getTemporaryAccessToken() {
            String url = WechatAPI.ACCESS_TOKEN_URL.replace("APPID", APPID).replace("APPSECRET", APPSECRET);
            String s = HttpClientUtil.doGet(url);
            JSONObject jsonObject = new JSONObject(s);
            if(jsonObject.has("access_token")){
                return jsonObject.get("access_token").toString();
            }
        return "";
    }

    /**
     * 获取jsapi_ticket
     * @return
     */
    private static String getJsApiTicket() {
        Object jsapi_ticket = redisTemplate.opsForValue().get("jsapi_ticket");
        if(jsapi_ticket == null){
            String url = WechatAPI.JSAPI_TICKET_URL.replace("ACCESS_TOKEN", getAccessToken());
            String s = HttpClientUtil.doGet(url);
            logger.debug("jsapi_ticket ： " + s);
            JSONObject jsonObject = new JSONObject(s);
            if(jsonObject.has("ticket")){
                jsapi_ticket = jsonObject.get("ticket");
                redisTemplate.opsForValue().set("jsapi_ticket", jsapi_ticket.toString(), 2, TimeUnit.HOURS);
            }
        }
        return jsapi_ticket.toString();
    }

    /**
     * 获取js接口权限签名
     * @param url
     * @return
     */
    public static Map<String, String> getSignature(String url){
        String jsapi_ticket = getJsApiTicket();
        String noncestr = Tools.getNoncestr();
        String timestamp = System.currentTimeMillis()/1000 + "";
        String str = "jsapi_ticket=" + jsapi_ticket +
                "&noncestr=" +noncestr +
                "&timestamp=" +timestamp +
                "&url=" + url;
        String signature = Tools.getSha1Str(str);
        Map<String, String> map = new HashMap<>();
        map.put("appId", APPID);
        map.put("timestamp", timestamp);
        map.put("nonceStr", noncestr);
        map.put("signature", signature);
        logger.debug("getSignature ： " + map.toString());
        return map;
    }

    /**
     * 通过code换取AccessToken&openid
     * @param code
     * @return
     */
//    public static JSONObject getAccessTokenByCode(String code){
//        String url = WechatAPI.OAUTH_ACCESSTOKEN_URL.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code);
//        String s = HttpClientUtil.doGet(url);
//        JSONObject jsonObject = new JSONObject(s);
//        logger.debug("getAccessTokenByCode ： " + jsonObject.toString());
//        if(jsonObject.has("openid")){
//            return jsonObject;
//        }
//        return null;
//    }
    public static JSONObject getAccessTokenByCode(String code){
        String url = WechatAPI.OAUTH_ACCESSTOKEN_URL.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code);
        String s = HttpClientUtil.doGet(url);
        JSONObject jsonObject = null;
        try {
            jsonObject = new JSONObject(s);
        } catch (JSONException e) {
            e.printStackTrace();
        }
        logger.debug("getAccessTokenByCode ： " + jsonObject.toString());
        if(jsonObject.has("openid")){
            return jsonObject;
        }
        return null;
    }

    /**
     * 调用获取微信用户信息接口UnionID机制
     * @param openid
     * @return
     */
    public static WxUser getWxUserInfoByUnionID(String openid){

        String url = WechatAPI.WXUSERINFO_UNIONID_URL.replace("ACCESS_TOKEN", getAccessToken()).replace("OPENID", openid);
        String s = HttpClientUtil.doGet(url);
        logger.debug("getWxUserInfoByUnionID ： " + s);
        return GsonUtil.josnToModule(s, WxUser.class);
    }

    /**
     * 发送模板消息
     * @param data
     * @return
     */
    public static boolean sendTemplate(String data){
        String url = WechatAPI.SENDTEMPLATE_URL.replace("ACCESS_TOKEN", getAccessToken());
        String s = HttpClientUtil.doPost(url, data);
        logger.debug("sendTemplate ： " + s);
        JSONObject jsonObject = new JSONObject(s);
        if(jsonObject.get("errcode").toString().equals("0")){
            return true;
        }
        return false;
    }

    /**
     * 挂号成功模板; 候诊时间： {{keyword1.DATA}} 就诊医院： {{keyword2.DATA}} 就诊科室： {{keyword3.DATA}} 就诊人： {{keyword4.DATA}} 备注： {{remark.DATA}}
     * 退号成功模板; 就诊人： {{keyword4.DATA}} 就诊医院： {{keyword2.DATA}} 就诊科室： {{keyword3.DATA}} 候诊时间： {{keyword1.DATA}}
     * @param map   openid, template_id, url, waitingTime, hospital, department, patient
     * @return
     */
    public static String registrationOrWithdrawal(Map<String, Object> map){
        JSONObject json = new JSONObject();
        json.put("touser", map.get("openid").toString());
        json.put("template_id", map.get("template_id").toString());
        json.put("url", map.get("url").toString());
        JSONObject data = new JSONObject();
        JSONObject keyword1 = new JSONObject();
        keyword1.put("value", map.get("waitingTime").toString());
        JSONObject keyword2 = new JSONObject();
        keyword2.put("value", map.get("hospital").toString());
        JSONObject keyword3 = new JSONObject();
        keyword3.put("value", map.get("department").toString());
        JSONObject keyword4 = new JSONObject();
        keyword4.put("value", map.get("patient").toString());
        JSONObject remark = new JSONObject();
        remark.put("value", map.get("remark"));
        data.put("keyword1", keyword1);
        data.put("keyword2", keyword2);
        data.put("keyword3", keyword3);
        data.put("keyword4", keyword4);
        data.put("remark", remark);
        json.put("data", data);
        return json.toString();
    }

    public static void main(String[] args) {
        //测试挂号，退号，注意替换调用临时AccessToken的方法
        Map<String, Object> map = new HashMap<>();
        map.put("openid", "o6wR757lCGdsqYXawJd4EojqKn24");
        map.put("template_id", Constant.TEMPLATE_ID_WITHDRAWAL_SUCCESS);
        map.put("url", "http://www.baidu.com");
        map.put("waitingTime", "2020/03/29");
        map.put("hospital", "解放军301医院");
        map.put("department", "外科");
        map.put("patient", "蜡笔小新");
        map.put("remark", "建议您使用公共交通等绿色出行方式，提前做好规划");
        String s = registrationOrWithdrawal(map);
        sendTemplate(s);
    }

}
